package com.link2room.rodimus.facade.impl;

import com.link2room.common.constant.BaseConstant;
import com.link2room.common.constant.DefaultValue;
import com.link2room.common.jpa.result.QueryResult;
import com.link2room.common.mns.MNSUtil;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.ClassConverUtil;
import com.link2room.common.util.JacksonUtil;
import com.link2room.common.util.L2RAssert;
import com.link2room.enums.exception.RodimusSysExceptionEnum;
import com.link2room.jetfire.constant.JetfireMnsConstant;
import com.link2room.jetfire.constant.ReservationConstant;
import com.link2room.jetfire.dto.param.inside.ReservationNmsStaInsideParamDto;
import com.link2room.jetfire.dto.param.inside.ReservationPayInsideParamDto;
import com.link2room.rodimus.dto.param.base.PointBaseParamDto;
import com.link2room.rodimus.dto.param.base.PointRuleBaseParamDto;
import com.link2room.rodimus.dto.result.base.PointCheckDto;
import com.link2room.rodimus.dto.result.base.PointRuleDetailDto;
import com.link2room.rodimus.dto.result.base.PointRuleDto;
import com.link2room.rodimus.dto.result.base.PointUseDatesDto;
import com.link2room.rodimus.entity.PointRule;

import com.link2room.rodimus.exception.RodimusException;
import com.link2room.rodimus.facade.IPointFacadeService;
import com.link2room.rodimus.feign.jetfire.ReservationsFeignService;
import com.link2room.rodimus.feign.soundwave.PmsMemberFeignService;
import com.link2room.soundwave.dto.param.inside.MemberLoginInsideParamDto;
import com.link2room.soundwave.dto.param.inside.PointPresentUseInsideParamDto;
import com.link2room.soundwave.dto.result.base.PmsMemberPointDto;
import com.link2room.trailbreaker.constant.Pay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;

/**
 * Created by sss on 2017/4/18.
 */
@Component("pointFacadeService")
public class PointFacadeServiceImpl implements IPointFacadeService {
    @Resource
    private ICommonService commonService;
    @Autowired
    private PmsMemberFeignService pmsMemberFeignService;
    @Resource
    private MNSUtil mnsUtil;
    @Resource
    private ReservationsFeignService reservationsFeignService;


    @Override
    public QueryResult<PointRuleDto> getPointRules(PointRuleBaseParamDto pointRuleBaseParamDto) throws Exception {
        String lhotelGroupCode = pointRuleBaseParamDto.getLhotelGroupCode();
        L2RAssert.stringBlank(lhotelGroupCode,"[lhotelGroupCode] is null.");
        PointRule queryPR=new PointRule();
        queryPR.setLhotelGroupCode(lhotelGroupCode);
        QueryResult<PointRule> pointRuleResult = commonService.findAllEQ(PointRule.class, queryPR, pointRuleBaseParamDto.getCurrentPage(), pointRuleBaseParamDto.getPageSize());
        return ClassConverUtil.copyQueryResultToDtoQueryResult(pointRuleResult,PointRuleDto.class,false);
    }

    @Override
    public PointRuleDto getPonitRuleByPointRuleCode(PointRuleBaseParamDto pointRuleBaseParamDto) throws Exception {
        PointRule queryPR=new PointRule();
        queryPR.setLhotelGroupCode(pointRuleBaseParamDto.getLhotelGroupCode());
        queryPR.setPointRuleCode(pointRuleBaseParamDto.getPointRuleCode());
        PointRule pointRule=commonService.findOneEQ(PointRule.class,queryPR);
        PointRuleDto pointRuleDto=ClassConverUtil.copyPropertiesToDto(pointRule,PointRuleDto.class,false);
        pointRuleDto.setPointRuleDetailDtoList(JacksonUtil.jsonToBeanByJavaType(pointRule.getPointRuleDetail(), ArrayList.class, PointRuleDetailDto.class));
        if(DefaultValue.T.equals(pointRule.getIsUseDates())){
            pointRuleDto.setPointUseDatesDtoList(JacksonUtil.jsonToBeanByJavaType(pointRule.getPointUseDates(), ArrayList.class, PointUseDatesDto.class));
        }
        return pointRuleDto;
    }

    @Override
    public void usePoint(PointBaseParamDto pointBaseParamDto)throws Exception{
        PointPresentUseInsideParamDto pointPresentUseInsideParamDto=ClassConverUtil.copyProperties(pointBaseParamDto,PointPresentUseInsideParamDto.class);
        pmsMemberFeignService.usePoint(pointPresentUseInsideParamDto);
    }

    @Override
    public void addPoint(PointBaseParamDto pointBaseParamDto)throws Exception{
        PointPresentUseInsideParamDto pointPresentUseInsideParamDto=ClassConverUtil.copyProperties(pointBaseParamDto,PointPresentUseInsideParamDto.class);
        pmsMemberFeignService.addPoint(pointPresentUseInsideParamDto);
    }

    @Override
    public PointCheckDto checkPointUse(PointBaseParamDto pointBaseParamDto) throws Exception{
        MemberLoginInsideParamDto memberLoginInsideParamDto=new MemberLoginInsideParamDto();
        memberLoginInsideParamDto.setLhotelCode(pointBaseParamDto.getLhotelCode());
        memberLoginInsideParamDto.setL2RMemberNo(pointBaseParamDto.getL2rMemberNo());
        PmsMemberPointDto pmsMemberPointDto = pmsMemberFeignService.getPMSMemberPoints(memberLoginInsideParamDto.paramToMap()).getResultInfo();
        BigDecimal memberPoint=null;
        if(pmsMemberPointDto!=null){
            memberPoint=pmsMemberPointDto.getPointBalance();
        }
        PointRuleBaseParamDto pointRuleBaseParamDto=new PointRuleBaseParamDto();
        pointRuleBaseParamDto.setPointRuleCode(pointBaseParamDto.getPointRuleCode());
        PointRuleDto pointRule = this.getPonitRuleByPointRuleCode(pointRuleBaseParamDto);
        if(pointRule!=null){
            BigDecimal totalPriceSale=pointBaseParamDto.getTotalPriceSale();
            boolean canUsePointFlag=false;
            boolean canUsePointDateFlag=false;
            boolean isAllow=false;
            Long now=System.currentTimeMillis();
            if(now>=pointRule.getStartDate().getTime()&&now<=pointRule.getEndDate().getTime()){
                isAllow=true;
            }
            PointCheckDto pointCheckDto=new PointCheckDto();
            BigDecimal promotionMoney=null;
            BigDecimal usePoint=null;
            for(PointRuleDetailDto pointRuleDetail:pointRule.getPointRuleDetailDtoList()){
                if(totalPriceSale.compareTo(pointRuleDetail.getMinPrice())>-1&&totalPriceSale.compareTo(pointRuleDetail.getMaxPrice())<1){
                    promotionMoney=totalPriceSale.multiply(pointRuleDetail.getMultiplyValue()).setScale(0, BigDecimal.ROUND_FLOOR);
                    usePoint=(promotionMoney.divide(pointRuleDetail.getMoney()).setScale(0, BigDecimal.ROUND_FLOOR))
                            .multiply(new BigDecimal(pointRuleDetail.getUsePoint()));
                    if(memberPoint!=null&&memberPoint.compareTo(usePoint)>-1){
                        canUsePointFlag=true;
                    }
                }
            }
            if(DefaultValue.T.equals(pointRule.getIsUseDates())){
                for(PointUseDatesDto useDate:pointRule.getPointUseDatesDtoList()){
                    if(pointBaseParamDto.getArrDate().getTime()>=useDate.getUseStartDate().getTime()
                            &&pointBaseParamDto.getDepDate().getTime()<=useDate.getUseEndDate().getTime()){
                        canUsePointDateFlag=true;
                    }
                }
            }else {
                canUsePointDateFlag=true;
            }
            if(canUsePointFlag&&canUsePointDateFlag&&isAllow){
                pointCheckDto.setCanUsePoint(DefaultValue.T);
                pointCheckDto.setPointToMoney(promotionMoney);
                pointCheckDto.setUsePoint(usePoint.intValue());
                pointCheckDto.setPointPayTaCode(pointRule.getTaCode());
            }else {
                pointCheckDto.setCanUsePoint(DefaultValue.F);
                pointCheckDto.setPointToMoney(new BigDecimal(0));
            }
            return pointCheckDto;
        }else {
            throw new RodimusException(RodimusSysExceptionEnum.POINT_RULE_NOT_EXIT);
        }
    }

    @Override
    public void reservationPoint(PointBaseParamDto pointBaseParamDto)throws Exception{
        ReservationNmsStaInsideParamDto reservationNmsStaParam = new ReservationNmsStaInsideParamDto();
        reservationNmsStaParam.setOptId(pointBaseParamDto.getOptId());
        reservationNmsStaParam.setLhotelGroupCode(pointBaseParamDto.getLhotelGroupCode());
        reservationNmsStaParam.setLhotelCode(pointBaseParamDto.getLhotelCode());
        reservationNmsStaParam.setL2RNo(pointBaseParamDto.getL2RNo());
        reservationNmsStaParam.setOperType(pointBaseParamDto.getOperType());
        reservationNmsStaParam.setItem(BaseConstant.ServiceCategoryConstant.RODIMUS);
        try {
            if(ReservationConstant.OPERTYPE.CREATE.equals(pointBaseParamDto.getOperType())){
                this.usePoint(pointBaseParamDto);
                ReservationPayInsideParamDto payParamDto = new ReservationPayInsideParamDto();
                payParamDto.setLhotelCode(pointBaseParamDto.getLhotelCode());
                payParamDto.setLhotelGroupCode(pointBaseParamDto.getLhotelGroupCode());
                payParamDto.setTaNo("point"+pointBaseParamDto.getL2RNo());
                payParamDto.setPayChannel(Pay._Channel.L2R);
                payParamDto.setPayType(Pay._Type.L2R.L2R_PROMOTION);
                payParamDto.setAmount(pointBaseParamDto.getPointToMoney());
                payParamDto.setOrderNo(pointBaseParamDto.getL2RNo());
                payParamDto.setRemark("积分抵扣："+payParamDto.getAmount());
                payParamDto.setTaCode(pointBaseParamDto.getTaCode());
                payParamDto.setLimitOnce(DefaultValue.F);
                try {
                    reservationsFeignService.payment(payParamDto);
                }catch (Exception e){
                    this.addPoint(pointBaseParamDto);
                    throw e;
                }
            }else if(ReservationConstant.OPERTYPE.REVERT.equals(pointBaseParamDto.getOperType())){
                this.addPoint(pointBaseParamDto);
            }
            reservationNmsStaParam.setOperSta(DefaultValue.T);
        }catch (Exception e) {
            reservationNmsStaParam.setOperSta(DefaultValue.F);
            throw e;
        }
        finally {
            mnsUtil.putMessageToQueue(JetfireMnsConstant.QUEUE_ORDER_STA, JacksonUtil.beanToJson(reservationNmsStaParam));
            //pmsMember信息不在session中存放，提供新接口
            /*MemberSessionBaseParamDto memberSessionBaseParamDto=new MemberSessionBaseParamDto();
            memberSessionBaseParamDto.setMemberNo(pointBaseParamDto.getL2rMemberNo());
            rodimusAPIService.refreshMemberSession(memberSessionBaseParamDto);*/
        }
    }
}
